package pl.gettoknowme.mobile.android.services.location;

import pl.gettoknowme.mobile.android.model.DBAdapter;
import pl.gettoknowme.mobile.android.model.dao.LocationDAO;
import pl.gettoknowme.mobile.android.util.LoggingUtil;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Looper;

/**
 * Wątek pobierający lokalizację
 * @author Michał Kołodziejski
 */
public class LocationGetterRunnable implements Runnable {
    
    private Context context;
    private LocationManager locationManager;
    private LocationListener locationListener;
    
    /**
     * Tworzy wątek pobierający lokalizację
     * @param context kontekst działania
     */
    public LocationGetterRunnable(Context context) {
        this.context = context;
    }
    
    
    @Override
    public void run() {
        LoggingUtil.d(this, "Thread to get locations - started");
        Looper.prepare();
        
        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        locationListener = getNewLocationListener();

        LoggingUtil.d(this, "Starting getting locations");
        
        if(startGettingLocation()){
            LoggingUtil.d(this, "After sending request for updates, before Looper.loop()");
            
            Looper.loop();
            
            LoggingUtil.d(this, "After Looper.loop()");
        }
        
    }
    
    
    /**
     * Rozpoczyna pobieranie lokalizacji
     * @param locationManager manager lokalizacji
     * @param locationListener listener
     */
    private boolean startGettingLocation(){
        Criteria criteria = new Criteria();
        criteria.setCostAllowed(false);
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        String provider = locationManager.getBestProvider(criteria, true);
        
        if(provider != null){
            locationManager.requestLocationUpdates(provider, 1000l,
                    0, locationListener);
            return true;
            
        } else {
            LoggingUtil.e(this, "Location provider == null");
            return false;
        }
    }

    /**
     * Zatrzymuje pobieranie lokalizacji
     */
    private void stopGettingLocation(){
        if(locationListener != null){
            locationManager.removeUpdates(locationListener);
            locationListener = null;
        }
    }
    

    /**
     * Zapisuje lokalizację do bazy danych
     * @param location lokalizacja
     */
    private void saveLocation(Location location) {
        LoggingUtil.d(this, "Saving location");
        
        // wstawiamy nową wartość do bazy danych
        pl.gettoknowme.mobile.android.model.dbtypes.Location dbLocation = 
            new pl.gettoknowme.mobile.android.model.dbtypes.Location();
        dbLocation.setFetchTime(System.currentTimeMillis());
        dbLocation.setLongitude(location.getLongitude());
        dbLocation.setLatitude(location.getLatitude());
        
        DBAdapter dbAdapter = DBAdapter.getInstance(context);
        LocationDAO locationDAO = dbAdapter.getLocationDAO();
        locationDAO.insert(dbLocation);
    }

    /**
     * Tworzy i zwraca nowego odbiorcę lokalizacji
     * @return odbiorca lokalizacji
     */
    protected LocationListener getNewLocationListener(){
        return new LocationListener() {
            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // nic
            }
            @Override
            public void onProviderEnabled(String provider) {
                // nic
            }
            @Override
            public void onProviderDisabled(String provider) {
                // nic
            }
            @Override
            public void onLocationChanged(Location location) {
                StringBuffer sb = new StringBuffer();
                sb.append("New location fetched!")
                    .append(" [longitude=")
                    .append(location.getLongitude())
                    .append(", latitude=")
                    .append(location.getLatitude())
                    .append("]");
                LoggingUtil.d(this, sb.toString());
                
                saveLocation(location);
                
                stopGettingLocation();
                
                Looper.myLooper().quit();
            }
        };
    }
}
